import { BezierPath } from './bezierPath'

export class Frame {
  alpha = 0.0
  
  transform = {
    a: 1.0,
    b: 0.0,
    c: 0.0,
    d: 1.0,
    tx: 0.0,
    ty: 0.0
  }
  
  layout = {
    x: 0.0,
    y: 0.0,
    width: 0.0,
    height: 0.0
  }
  
  nx = 0.0
  ny = 0.0
  
  maskPath?: BezierPath
  
  shapes: any[] = []
  
  static lastShapes: any
  
  constructor(props: any) {
    this.alpha = parseFloat(props.alpha) || 0.0
    if (props.layout) {
      this.layout.x = parseFloat(props.layout.x) || 0.0
      this.layout.y = parseFloat(props.layout.y) || 0.0
      this.layout.width = parseFloat(props.layout.width) || 0.0
      this.layout.height = parseFloat(props.layout.height) || 0.0
    }
    
    if (props.transform) {
      this.transform.a = parseFloat(props.transform.a) || 1.0
      this.transform.b = parseFloat(props.transform.b) || 0.0
      this.transform.c = parseFloat(props.transform.c) || 0.0
      this.transform.d = parseFloat(props.transform.d) || 1.0
      this.transform.tx = parseFloat(props.transform.tx) || 0.0
      this.transform.ty = parseFloat(props.transform.ty) || 0.0
    }
    
    if (props.clipPath?.length) {
      this.maskPath = new BezierPath(props.clipPath, undefined, { fill: '#000000' })
    }
    
    if (props.shapes) {
      props.shapes?.forEach((v: any) => {
        v.pathArgs = v.args
        switch (v.type) {
          case 0:
            v.type = 'shape'
            v.pathArgs = v.shape
            break
          case 1:
            v.type = 'rect'
            v.pathArgs = v.rect
            break
          case 2:
            v.type = 'ellipse'
            v.pathArgs = v.ellipse
            break
          case 3:
            v.type = 'keep'
            break
        }
        
        if (v.styles) {
          if (v.styles.fill) {
            if (typeof v.styles.fill.r === 'number') v.styles.fill[0] = v.styles.fill.r
            if (typeof v.styles.fill.g === 'number') v.styles.fill[1] = v.styles.fill.g
            if (typeof v.styles.fill.b === 'number') v.styles.fill[2] = v.styles.fill.b
            if (typeof v.styles.fill.a === 'number') v.styles.fill[3] = v.styles.fill.a
          }
          
          if (v.styles.stroke) {
            if (typeof v.styles.stroke.r === 'number') v.styles.stroke[0] = v.styles.stroke.r
            if (typeof v.styles.stroke.g === 'number') v.styles.stroke[1] = v.styles.stroke.g
            if (typeof v.styles.stroke.b === 'number') v.styles.stroke[2] = v.styles.stroke.b
            if (typeof v.styles.stroke.a === 'number') v.styles.stroke[3] = v.styles.stroke.a
          }
          
          let lineDash = v.styles.lineDash || []
          if (v.styles.lineDashI > 0) lineDash.push(v.styles.lineDashI)
          if (v.styles.lineDashII > 0) {
            if (lineDash.length < 1) lineDash.push(0)
            
            lineDash.push(v.styles.lineDashII)
            lineDash.push(0)
          }
          if (v.styles.lineDashIII > 0) {
            if (lineDash.length < 2) {
              lineDash.push(0)
              lineDash.push(0)
            }
            lineDash[2] = v.styles.lineDashIII
          }
          v.styles.lineDash = lineDash
          
          switch (v.styles.lineJoin) {
            case 0:
              v.styles.lineJoin = 'miter'
              break
            case 1:
              v.styles.lineJoin = 'round'
              break
            case 2:
              v.styles.lineJoin = 'bevel'
          }
          
          switch (v.styles.lineCap) {
            case 0:
              v.styles.lineCap = 'butt'
              break
            case 1:
              v.styles.lineCap = 'round'
              break
            case 2:
              v.styles.lineCap = 'square'
              break
          }
        }
      })
      
      if (props.shapes[0] && props.shapes[0].type === 'keep') {
        this.shapes = Frame.lastShapes
      } else {
        this.shapes = props.shapes
        Frame.lastShapes = props.shapes
      }
    }
    const { a, b, c, d, tx, ty } = this.transform
    const { x, y, width, height } = this.layout
    const llx = a * x + c * y + tx
    const lrx = a * (x + width) + c * y + tx
    const lbx = a * x + c * (y + height) + tx
    const rbx = a * (x + width) + c * (y + height) + tx
    
    const lly = b * x + d * y + ty
    const lry = b * (x + width) + d * y + ty
    const lby = b * x + d * (y + height) + ty
    const rby = b * (x + width) + d * (y + height) + ty
    
    this.nx = Math.min(Math.min(lbx, rbx), Math.min(llx, lrx))
    this.ny = Math.min(Math.min(lby, rby), Math.min(lly, lry))
  }
}